# ==============================================================================
# DESCRIPTION ----
# ==============================================================================
# This script installs all R package dependencies needed for the analyses. 
# Run this script once before running any other .R scripts.

# ==============================================================================
# CHECK IF LIBRARIES (AND CORRECT VERSIONS OF LIBRARIES) ARE INSTALLED ---
# INSTALL AND/OR UPDATE LIBRARIES IF NOT ---
# ==============================================================================
# List of required packages to install at latest version -----------------------
cran_packages_latest <- c(
  "tidyverse", "janitor", "lubridate", "formattable", "gt",
  "kableExtra", "sparkline", "igraph", "circlize", "viridis",
  "scales", "hablar", "ggridges", "gridExtra", "modelsummary",
  "naniar", "visdat", "DeclareDesign", "tidyquant", "eventstudies",
  "plm", "panelView", "benford.analysis", "tsibble"
)

# List of required packages with strict version requirements -------------------
cran_packages_strict <- list(
  DIDmultiplegt = "0.1.0",
  fect          = "1.0.0",
  PanelMatch    = "3.0.0"
)

# Helper functions -------------------------------------------------------------
install_if_missing <- function(pkg) {
  if (!requireNamespace(pkg, quietly = TRUE)) {
    message(paste("Installing", pkg, "from CRAN (latest)..."))
    install.packages(pkg, dependencies = TRUE)
  } else {
    message(paste(pkg, "is already installed (latest CRAN version assumed)."))
  }
}

install_cran_strict <- function(pkg, version) {
  if (!requireNamespace("remotes", quietly = TRUE)) {
    message("Installing 'remotes' package...")
    install.packages("remotes")
  }
  
  installed <- FALSE
  current_version <- NULL
  if (requireNamespace(pkg, quietly = TRUE)) {
    installed <- TRUE
    current_version <- as.character(utils::packageVersion(pkg))
  }
  
  if (!installed || current_version != version) {
    if (installed) {
      message(paste("Reinstalling", pkg, "to enforce version", version, 
                    "(currently", current_version, ")..."))
    } else {
      message(paste("Installing", pkg, "version", version, "from CRAN..."))
    }
    remotes::install_version(pkg, version = version, repos = "http://cran.us.r-project.org")
  } else {
    message(paste(pkg, "is already at required version", version))
  }
}

# Install All Packages ----
message("Checking and installing required CRAN packages (latest)...\n")
invisible(lapply(cran_packages_latest, install_if_missing))

message("\nChecking and enforcing strict CRAN package versions...\n")
for (pkg in names(cran_packages_strict)) {
  install_cran_strict(pkg, cran_packages_strict[[pkg]])
}

message("\nall required packages are installed at the correct versions")
